#include "MapScene.h"
#include "Camera.h"
#include <algorithm>
#include "D3DUtil.h"
#include "D3DInput.h"
#include "D3DApp.h"
#include "tchar.h"
#include <string>

MapScene* gMapScene = 0;

MapScene::MapScene( std::string filename, std::string mapname) : mFont(0){
	mMapName	= mapname;
	mFileName	= filename;
	mBackground = new ObBackGround();
	mTime	= 600;
	mLife	= 0;
	mScore	= 0;
	mMap	= NULL;
	mNewObject.clear();
	canPause = true;

	D3DXFONT_DESC fontDesc;
	fontDesc.Height          = 20;
	fontDesc.Width           = 0;
	fontDesc.Weight          = 0;
	fontDesc.MipLevels       = 1;
	fontDesc.Italic          = false;
	fontDesc.CharSet         = DEFAULT_CHARSET;
	fontDesc.OutputPrecision = OUT_DEFAULT_PRECIS;
	fontDesc.Quality         = DEFAULT_QUALITY;
	fontDesc.PitchAndFamily  = DEFAULT_PITCH | FF_DONTCARE;
	strcpy_s(fontDesc.FaceName, _T("Hobo Std"));
	mTransparentGroundPos	= D3DXVECTOR3(0.0f, 0.0f, 0.0f);
	mTransparentGroundCenter= D3DXVECTOR3(8.0f, 8.0f, 0.0f);
	HR(D3DXCreateFontIndirect(gDevice, &fontDesc, &mFont));
}

MapScene::~MapScene(){
	mActiveObject.clear();
	mBackObject.clear();
	delete mMap;
	delete mBackground;
}

void MapScene::onLostDevice(){
	mFont->OnLostDevice();
}

void MapScene::onResetDevice(){
	mFont->OnResetDevice();
}

void MapScene::saveMap(){
	outfile.open("Maps\\SavedMap\\SavedMap.xdmap");
	for(unsigned int i = 0; i<mMap->getBackMap().size(); i++){
		if(mMap->getBackMap()[i]->mNeedDispose == false){
			outfile<<mMap->getBackMap()[i]->getSaveString().c_str()<<std::endl;
		}
	}
	outfile<<"END"<<std::endl;
	for(unsigned int i = 0; i<mMap->getChosedMap().size(); i++){
		if(mMap->getChosedMap()[i]->mNeedDispose == false){
			outfile<<mMap->getChosedMap()[i]->getSaveString().c_str()<<std::endl;
		}
		outfile<<mMap->getMario()->getSaveString().c_str()<<std::endl;
	}
	outfile<<"QUAD_BACK"<<std::endl;
	writeOut(mMap->getBackTree());
	outfile<<"QUAD_CHOSED"<<std::endl;
	writeOut(mMap->getChosedTree());
	outfile<<"MAP_TIME"<<std::endl;
	outfile<<mTime<<std::endl;
	outfile<<"MAP_NAME"<<std::endl;
	outfile<<mMap->mName<<std::endl;
	outfile.close();
}

void MapScene::writeOut(TreeNode* node){
	if(node == NULL) return;
	outfile<<node->getSaveString()<<std::endl;
	writeOut(node->northWest);
	writeOut(node->northEast);
	writeOut(node->southEast);
	writeOut(node->southWest);
}

void MapScene::setSetting(int life, int score, int state){
	if(ObPlayer* player = dynamic_cast<ObPlayer*> (mMap->getMario())){
		if(life >= 0){
			player->setLife(life);
		}
		player->setScore(score);
		switch (state)
		{
		case 1:
			player->setStatus(SMALL);
			break;
		case 2:
			player->setStatus(BIG);
			break;
		case 3:
			player->setStatus(FLOWER);
			break;
		}
	}
}

bool MapScene::loading(){
	isLoading = true;
	if(mMap != NULL){
		delete mMap;
		mMap = NULL;
	}
	mMap = new Map(mMapName,mFileName);
	if(mMap->mIsReady){
		loadTexture();
		gCamera->setMapSize(mMap->mContainer);
	}else{
		return false;
	}
	isLoading = false;
	mTime = mMap->MapTime;
	count = 0.0f;
	timePass = 0.0f;
	//
	return true;

}

SceneRS MapScene::update(float dt){
	mActiveObject.clear();
	mBackObject.clear();

	mTransparentGroundPos.y = gApp->mHeight/2 -8;
	SceneRS rs;
	rs.ID = -1;
	rs.Info = "";

	if(gInput->keyDown(DIK_ESCAPE) && canPause){
		rs.ID = 3;
		return rs;
	}

	timePass+=dt;
	if(timePass>= 1.0f){
		timePass = 0.0f;
		mTime--;
		if(mTime <= 0){
			if(mLife <= 0){
				rs.ID = 0; //het mang
				rs.Info = mScore;
			}else{
				rs.ID = 1; //con mang
				int life = mLife - 1;
				int score = mScore;
				rs.Info = std::to_string(life) + " " + std::to_string(score);
			}
		}
	}

	mMap->getBackTree()->clipCamera(gCamera->getAABB(),mBackObject);
	for(std::vector<ObObject*>::size_type i = 0; i != mBackObject.size();i++){
		mBackObject[i]->update(dt);
	}

	std::vector<ObObject*> temp;
	mMap->getChosedTree()->clipCamera(gCamera->getAABB(), temp);
	mActiveObject.clear();
	mActiveObject.push_back(mMap->getMario());
	mActiveObject.insert( mActiveObject.end(), mNewObject.begin(), mNewObject.end());
	mActiveObject.insert( mActiveObject.end(), temp.begin(), temp.end());

	CollisionRS rsMoving, rsStatic;
	float dtx, dty;
	bool  isCollided;
	for(std::vector<ObObject*>::size_type i = 0; i < mActiveObject.size();i++){
		if(mActiveObject[i]->mNeedDispose == true) continue;

		mActiveObject[i]->update(dt);

		ObDynamic* ob = dynamic_cast<ObDynamic*>(mActiveObject[i]);
		if(ob != NULL){
			dtx = dt; dty = dt; isCollided = false;
			if(mActiveObject[i]->mNeedCollision) {
				ob->mIsJump = true;
				for(std::vector<ObObject*>::size_type j = 0; j !=mActiveObject.size(); j++){
					if(i == j) continue;
					if(mActiveObject[j]->mNeedDispose == true) continue;
					if(mActiveObject[j]->mNeedCollision == false) continue;
					
					Collision::checkCollision(ob,mActiveObject[j],dt,false,rsMoving,rsStatic);
					if(rsMoving.mCollided){
						if(ob->getId() == ObPlayer::MARIO && mActiveObject[j]->getId() == ObBullet::BL1 
							|| mActiveObject[j]->getId() == ObPlayer::MARIO && ob->getId() == ObBullet::BL1){
								continue;
						}
						ob->collidedWith(mActiveObject[j],rsMoving);
						mActiveObject[j]->collidedWith(ob,rsStatic);
						isCollided= true;
						if(rsMoving.mState == Left || rsMoving.mState == Right){
							dtx = 0.0f;
						}else if(rsMoving.mState == Bottom){
							dty = 0.0f; 
							ob->mIsJump = false;
						}else if(rsMoving.mState == Top){
							dty = 0.0f;
						}

						
					}
				}
				if(isCollided == false && ob->getId() == ObPlayer::MARIO){
					if(ObPlayer* player = dynamic_cast<ObPlayer*> (mMap->getMario())){
						if(player->getVelocity().y > 0.0f || player->getVelocity().y < 0.0f){
							player->canRun = true;
						}
					}
				}
			}
			ob->updateMoving(dt, dtx, dty);
		}
	}

	if(ObPlayer* player = dynamic_cast<ObPlayer*> (mMap->getMario())){
		mLife	= player->getLife();
		mScore	= player->getScore();
		canPause = !player->isMapDone;
		if(player->getCurrentAction() == DIE){
			canPause = false;
		}
		if(player->getCurrentAction() == SAYGOODBYE){
			count +=dt;
			if(count >= 0.02f){
				mTime-=1;
				player->setScore(player->getScore() + 2);
				count = 0.0f;
				if(mTime <= 0){
					rs.ID = 2;
					int sctore = player->getScore();
					int life =  player->getLife();
					int state = player->getStatus();
					rs.Info = std::to_string(state) + std::to_string(life) + " " +std::to_string(sctore);
					return rs;
				}
			}
		}

		if(mMap->getMario()->mNeedDispose){
			if(player->getLife() <= 0){
				rs.ID = 0; //het mang
				rs.Info = player->getScore();
			}else{
				rs.ID = 1; //con mang
				int life = player->getLife() - 1;
				int score = player->getScore();
				int state = player->getStatus();
				rs.Info = std::to_string(state) + std::to_string(life) + " " + std::to_string(score);
			}
		}

	}

	return rs;
}

void MapScene::draw(ID3DXSprite* sprite){
	mBackground->render(sprite);
	for(unsigned int i = 0; i < mBackObject.size();i++){
		mBackObject[i]->render(sprite);
	}

	for(unsigned int i = 0; i < mActiveObject.size();i++){
		mActiveObject[i]->render(sprite);
	}
	drawTransparentGround(sprite);
	drawInfo(sprite);
}

void MapScene::drawTransparentGround(ID3DXSprite* sprite){
	if(mBackTex == 0) return;
	gDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE);
	D3DXMATRIX S;
	int time = gApp->mWidth/16 +1;
	D3DXMatrixScaling(&S,time,-1.0f, 0);
	D3DXMATRIX R;
	D3DXMatrixRotationZ(&R, 0);
	D3DXMATRIX T;
	D3DXMatrixTranslation(&T,mTransparentGroundPos.x, mTransparentGroundPos.y, 0);
	sprite->SetTransform(&(S*R*T));
	RECT rect;
	rect.left = 0;
	rect.right = 16;
	rect.top = 0;
	rect.bottom = 16;
	sprite->Draw(mBackTex,&rect,&mTransparentGroundCenter,0,D3DCOLOR_ARGB(100, 0, 0, 0)); 
	sprite->Flush();
	gDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,FALSE);
}
void MapScene::drawInfo(ID3DXSprite* sprite){
	static char buffer[256];
	std::string temp = "Life : " + std::to_string(mLife);
	sprintf_s(buffer, temp.c_str());
	RECT R1 = {100, 5, 0, 0};
	HR(mFont->DrawTextA(0,buffer,-1,&R1,DT_NOCLIP,D3DCOLOR_XRGB(227,227,227)));
	temp = "Time : " + std::to_string(mTime);
	sprintf_s(buffer, temp.c_str());
	RECT R2 = {350, 5, 0, 0};
	HR(mFont->DrawTextA(0,buffer,-1,&R2,DT_NOCLIP,D3DCOLOR_XRGB(227,227,227)));
	temp = "Score : " + std::to_string(mScore);
	sprintf_s(buffer, temp.c_str());
	RECT R3 = {600, 5, 0, 0};
	HR(mFont->DrawTextA(0,buffer,-1,&R3,DT_NOCLIP,D3DCOLOR_XRGB(227,227,227)));
}

void MapScene::loadTexture(){
	//==================BG CHECK
	needLoadBack.clear();
	ObBackGround::loadTexture();
	ObPlayer::loadTexture();

	for(unsigned int i = 0;i<mMap->getBackMap().size();i++){
		if(std::find(needLoadBack.begin(),needLoadBack.end(),mMap->getBackMap()[i]->getId())!=needLoadBack.end()){

		}else{
			int cur = mMap->getBackMap()[i]->getId();
			needLoadBack.push_back(cur);
			LoadTextureEX(ObCastle,cur);
			LoadTextureEX(ObCloud,cur);
			LoadTextureEX(ObGrass,cur);
			LoadTextureEX(ObMountain,cur);
			LoadTextureEX(ObBlackGround,cur);
			//....
		}
	}

	//==============NON BG CHECK
	needLoadChosed.clear();
	for(unsigned int i = 0;i<mMap->getChosedMap().size();i++){
		if(std::find(needLoadChosed.begin(),needLoadChosed.end(),mMap->getChosedMap()[i]->getId())!=needLoadChosed.end()){

		}else{
			int cur = mMap->getChosedMap()[i]->getId();
			needLoadChosed.push_back(cur);
			LoadTextureEX(ObBrick,cur);
			LoadTextureEX(ObBrickSP,cur);
			LoadTextureEX(ObPipe,cur);
			LoadTextureEX(EMushRoom,cur);
			LoadTextureEX(ETurtle,cur);
			LoadTextureEX(ObScoreTree,cur);
			LoadTextureEX(ObCoin,cur);
			//...
		}
	}

	mBackTex = 0;
	if(mBackTex == 0){
		D3DXCreateTextureFromFileEx(gDevice,"Sprites/ScoreBackground.png",
			D3DX_DEFAULT_NONPOW2,
			D3DX_DEFAULT_NONPOW2,
			0,
			0,
			D3DFMT_UNKNOWN,
			D3DPOOL_MANAGED,
			D3DX_DEFAULT,
			D3DX_DEFAULT,
			D3DCOLOR_XRGB(0,0,0),
			NULL,
			NULL,
			&mBackTex);
	}
}

void MapScene::releaseTexture(){
	ObBackGround::releaseTexture();
	ObPlayer::releaseTexture();
	for(unsigned int i = 0;i<needLoadBack.size();i++){
		ReleaseTextureEX(ObCastle,needLoadBack[i]);
		ReleaseTextureEX(ObCloud,needLoadBack[i]);
		ReleaseTextureEX(ObGrass,needLoadBack[i]);
		ReleaseTextureEX(ObMountain,needLoadBack[i]);
		ReleaseTextureEX(ObBlackGround,needLoadBack[i]);
		//...
	}

	for(unsigned int i = 0;i<needLoadChosed.size();i++){
		ReleaseTextureEX(ObBrick,needLoadChosed[i]);
		ReleaseTextureEX(ObBrickSP,needLoadChosed[i]);
		ReleaseTextureEX(ObPipe,needLoadChosed[i]);
		ReleaseTextureEX(EMushRoom,needLoadChosed[i]);
		ReleaseTextureEX(ETurtle,needLoadChosed[i]);
		ReleaseTextureEX(ObScoreTree,needLoadChosed[i]);
		ReleaseTextureEX(ObCoin,needLoadChosed[i]);
		//...

	}

	if(mBackTex != 0){
		ReleaseCOM(mBackTex);
	}
}
